home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000…tember: Reference Library / Dev.CD Sep 00 RL Disk 1.toast / mac / Technical Documentation / Develop / develop Issue 28 / develop Issue 28 code / MacApp Debugging / TwistDownLists / UVolumeBasedApp.cp < prev    next >
Encoding:
Text File  |  1996-07-15  |  25.6 KB  |  807 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UVolumeBasedApp.cp
  3. // ETO20 MacApp 3.3.1, MPW 3.4.1
  4. // Copyright ©1996 Conrad Kopala
  5. // Twist Down Lists version 2.0a0 7/15/96
  6. //----------------------------------------------------------------------------------------
  7.  
  8. #ifndef __UVOLUMEBASEDAPP__
  9. #include "UVolumeBasedApp.h"
  10. #endif
  11.  
  12. //needs gTwistDownApp for FailNIL(aDocument = gTwistDownApp -> DoMakeVolumeDocument(kindOfDocCmd, volumeOwnedByDoc));
  13. #ifndef __UTWISTDOWNAPP__
  14. #include "UTwistDownApp.h"    
  15. #endif
  16.  
  17. //needs errNotHFSVolume, msgNotHFSVolume
  18. #ifndef __UTWISTDOWNGLOBALS__
  19. #include "UTwistDownGlobals.h" 
  20. #endif
  21.  
  22. // MacApp
  23.  
  24. #ifndef __ULIST__
  25. #include "UList.h"
  26. #endif
  27.  
  28. //ToolBox stuff
  29. //None
  30.  
  31. //ANSI stuff
  32. //None
  33. //========================================================================================
  34. // CLASS MVolumeBasedApp
  35. //========================================================================================
  36. #undef Inherited
  37.  
  38.  
  39. #pragma segment MAInit
  40. MA_DEFINE_CLASS_M0(MVolumeBasedApp);
  41.  
  42. //----------------------------------------------------------------------------------------
  43. // MVolumeBasedApp::MVolumeBasedApp
  44. //----------------------------------------------------------------------------------------
  45. #pragma segment MAInit
  46. MVolumeBasedApp::MVolumeBasedApp()
  47. {
  48. #if qDebug
  49. if (gPrintAppClassInfo)
  50.     {
  51.         fprintf(stderr, " Construct MVolumeBasedApp");    //Cannot use  PrintAppConstructorClassInfo()
  52.                                                                                                         //because MVolumeBasedApp does not descend
  53.                                                                                                         //from TObject.
  54.         fprintf(stderr, "\n");
  55.     }
  56. #endif
  57. }
  58. //----------------------------------------------------------------------------------------
  59. // MVolumeBasedApp destructor
  60. //----------------------------------------------------------------------------------------
  61. #pragma segment MADestructorRes
  62. MVolumeBasedApp::~MVolumeBasedApp()
  63. {
  64. #if qDebug
  65. if (gPrintAppClassInfo)
  66.     {
  67.         fprintf(stderr, " Destruct MVolumeBasedApp");    //Cannot use  PrintAppDestructorClassInfo()
  68.                                                                                                     //because MVolumeBasedApp does not descend
  69.                                                                                                     //from TObject.
  70.         fprintf(stderr, "\n");
  71.     }
  72. #endif
  73. }
  74. //----------------------------------------------------------------------------------------
  75. // MVolumeBasedApp::DoMakeVolume    analog of DoMakeFile
  76. //----------------------------------------------------------------------------------------
  77. #pragma segment AOpen
  78. TVolume* MVolumeBasedApp::DoMakeVolume()
  79. {
  80. return NewVolume(gApplication -> fCreator);
  81. }
  82. //----------------------------------------------------------------------------------------
  83. // MVolumeBasedApp::ChooseVolume:    analog of ChooseDocument new version
  84. //----------------------------------------------------------------------------------------
  85. #pragma segment AOpen
  86. Boolean MVolumeBasedApp::ChooseVolume(CommandNumber itsCommandNumber, TList** aVolumeList)
  87. {
  88.  
  89.     typedef SFTypeList* SFTypeListPtr;
  90.     typedef SFTypeListPtr* SFTypeListHandle;
  91.  
  92.     
  93.     MAVolatileInit(TVolume*, aVolume, NULL);
  94.     Boolean volumeChosen;
  95.  
  96. #if !qPowerPC && !qModelCFM
  97.     if (HasCustomFile())
  98.     {
  99. #endif
  100.         ProcPtr fileFilter;
  101.         TypeListHandle typeList;
  102.         short dlgID;
  103.         CPoint where;
  104.         ProcPtr dlgHook;
  105.         ProcPtr modalFilter;
  106.         Ptr activeList;
  107.         ProcPtr activateProc;
  108.         StandardFileReply customReply;
  109.         void* yourDataPtr = NULL;
  110.         
  111.         gApplication -> GetStandardFileParameters(itsCommandNumber, fileFilter, typeList, dlgID, where,
  112.                                         dlgHook, modalFilter, activeList, activateProc,
  113.                                         &customReply, yourDataPtr);
  114.     
  115.         SFTypeListPtr pTypeList;
  116.         short numTypes = (short)(GetHandleSize((Handle)typeList) / sizeof(ResType));
  117.         if (numTypes == 0)
  118.         {
  119.             numTypes = -1;                            // Tell Std File to display all types.
  120.             pTypeList = (SFTypeListPtr) & pTypeList;// arbitrary, as long as it points to 4 bytes of valid memory
  121.         }
  122.         else
  123.         {
  124.             LockHandleHigh((Handle)typeList);        // in case Std File does allocations 
  125.             pTypeList = *((SFTypeListHandle)typeList);
  126.         }
  127.     
  128.         // Causes TApplication::GetEvent to call CheckRsrcUsage. 
  129.         gRsrcCheck = 0;
  130.     
  131.         FailInfo fi;
  132.         Try(fi)
  133.         {
  134.     
  135.             aVolume = this -> DoMakeVolume();
  136.             volumeChosen = FALSE;
  137.     
  138.             FailOSErr(gApplication->InteractWithUser(gNotificationPtr, TAppleEvent::fgIdleProc)); 
  139.     
  140.             if (yourDataPtr == NULL)
  141.                 yourDataPtr = &itsCommandNumber;
  142.             
  143.             gClipboardMgr->AboutToLoseControl(TRUE);            // so scrap gets converted
  144.             
  145.             FileFilterYDUPP cgfFileFilter = NewFileFilterYDProc(fileFilter);
  146.             DlgHookYDUPP cgfDlgHook = NewDlgHookYDProc(dlgHook);
  147.             ModalFilterYDUPP cgfModalFilter = NewModalFilterYDProc(modalFilter);
  148.             ActivateYDUPP cgfActivateProc = NewActivateYDProc(activateProc);
  149.  
  150.             CustomGetFile(cgfFileFilter, numTypes, (*pTypeList), &customReply, dlgID, where, cgfDlgHook, cgfModalFilter, (short*)activeList, cgfActivateProc, yourDataPtr);
  151.             
  152.             cgfFileFilter = (FileFilterYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfFileFilter);
  153.             cgfDlgHook = (DlgHookYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfDlgHook);
  154.             cgfModalFilter = (ModalFilterYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfModalFilter);
  155.             cgfActivateProc = (ActivateYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfActivateProc);
  156.             
  157.             gClipboardMgr->RegainControl(TRUE);            // so scrap gets converted
  158.  
  159.             volumeChosen = customReply.sfGood;
  160.             if (volumeChosen)
  161.                 {
  162.                 aVolume -> SpecifyWithStandardFileReply(customReply);
  163.     
  164.                 if (!(aVolume -> IsHFSVolume()))
  165.                     {
  166.                     CStr31 volumeName;
  167.                     aVolume -> GetName(volumeName);
  168.                     gErrorParm3 = volumeName;
  169.                     Failure(errNotHFSVolume, msgNotHFSVolume);
  170.                     }
  171.                 }
  172.                 
  173.             fi.Success();
  174.         }
  175.         else // Recover
  176.         {
  177.             typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  178.             aVolume = (TVolume *)FreeIfObject(aVolume);
  179.             fi.ReSignal();
  180.         }
  181.     
  182.         typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  183.  
  184.  
  185.  
  186. #if !qPowerPC && !qModelCFM
  187.         // the following block of code is the "else" block for the above Gestalt check - 
  188.         // as with that check, it is only relevant if we are not built for PowerPC
  189.     }
  190.     else
  191.     {
  192.         ProcPtr fileFilter;
  193.         TypeListHandle typeList;
  194.         short dlgID;
  195.         CPoint where;
  196.         ProcPtr dlgHook;
  197.         ProcPtr modalFilter;
  198.         Ptr activeList;
  199.         ProcPtr activateProc;
  200.         SFReply reply;
  201.         void* yourDataPtr = NULL;
  202.         
  203.         // We can't pass reply because it's a lowly SFReply, not a StandardFileReply
  204.         gApplication -> GetStandardFileParameters(itsCommandNumber, fileFilter, typeList, dlgID, where,
  205.                                         dlgHook, modalFilter, activeList, activateProc,
  206.                                         NULL, yourDataPtr);
  207.     
  208.         SFTypeListPtr pTypeList;
  209.         short numTypes = (short)(GetHandleSize((Handle)typeList) / sizeof(ResType));
  210.         if (numTypes == 0)
  211.         {
  212.             numTypes = -1;                            // Tell Std File to display all types.
  213.             pTypeList = (SFTypeListPtr) & pTypeList;// arbitrary, as long as it points to 4 bytes of valid memory
  214.         }
  215.         else
  216.         {
  217.             LockHandleHigh((Handle)typeList);        // in case Std File does allocations 
  218.             pTypeList = *((SFTypeListHandle)typeList);
  219.         }
  220.     
  221.         // Causes TApplication::GetEvent to call CheckRsrcUsage. 
  222.         gRsrcCheck = 0;
  223.     
  224.         FailInfo fi;
  225.         Try(fi)
  226.         {
  227.     
  228.             aVolume = this -> DoMakeVolume();
  229.             volumeChosen = FALSE;
  230.     
  231.             FailOSErr(gApplication->InteractWithUser(gNotificationPtr, TAppleEvent::fgIdleProc)); 
  232.     
  233.             if (yourDataPtr == NULL)
  234.                 yourDataPtr = &itsCommandNumber;
  235.             
  236.             // We will pass the address of the CallBack instead of the modalFilter to
  237.             // SFPGetFile It will add yourDataPtr parameter before passing on to the
  238.             // ModalFilterProc supplied by SFPutParms this lets us assume a single calling
  239.             // convention for that function.
  240.  
  241.             // Don't create a CallBack when the SF callback is NULL.
  242.             // Also, pass itsCommandNumber as a default yourDataPtr.
  243.             
  244.             CallBack myFileFilterCallBack;
  245.             SetCallBack(fileFilter, (long)yourDataPtr, &myFileFilterCallBack);
  246.             FileFilterProcPtr aFileFilterProcPtr = fileFilter ? (FileFilterProcPtr)&myFileFilterCallBack : NULL;
  247.  
  248.             CallBack myModalHookCallBack;
  249.             SetCallBack(dlgHook, (long)yourDataPtr, &myModalHookCallBack);
  250.             DlgHookProcPtr aDlgHookProcPtr = dlgHook ? (DlgHookProcPtr)&myModalHookCallBack : NULL;
  251.     
  252.             CallBack myModalFilterCallBack;
  253.             SetCallBack(modalFilter, (long)yourDataPtr, &myModalFilterCallBack);
  254.             ModalFilterProcPtr aModalFilterProcPtr = modalFilter ? (ModalFilterProcPtr)&myModalFilterCallBack : NULL;
  255.  
  256.             gClipboardMgr->AboutToLoseControl(TRUE);    // so scrap gets converted
  257.  
  258.             SFPGetFile(where, gEmptyString, aFileFilterProcPtr, numTypes, (*pTypeList), aDlgHookProcPtr, &reply, dlgID, aModalFilterProcPtr);
  259.             
  260.             gClipboardMgr->RegainControl(TRUE);            // so scrap gets converted
  261.  
  262.             volumeChosen = reply.good;
  263.  
  264.             if (volumeChosen)
  265.                 {
  266.                 FailOSErr(aVolume -> SpecifyWithSFReply(reply));
  267.     
  268.                 if (!(aVolume -> IsHFSVolume()))
  269.                     {
  270.                     CStr31 volumeName;
  271.                     aVolume -> GetName(volumeName);
  272.                     gErrorParm3 = volumeName;
  273.                     Failure(errNotHFSVolume, msgNotHFSVolume);
  274.                     }
  275.                 }
  276.                 
  277.             fi.Success();
  278.         }
  279.         else // Recover
  280.         {
  281.             typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  282.             aVolume = (TVolume *)FreeIfObject(aVolume);
  283.             fi.ReSignal();
  284.         }
  285.     
  286.         typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  287.  
  288.     }
  289. #endif
  290.  
  291.     if (volumeChosen)
  292.     {
  293.         MAVolatileInit(TList**, volatileVolumeList, aVolumeList);
  294.         
  295.         FailInfo fi;
  296.         Try(fi)
  297.         {
  298.             // Return the file(s) chosen 
  299.             *volatileVolumeList = NewList();
  300.             (*volatileVolumeList)->InsertLast(aVolume);
  301.             fi.Success();
  302.         }
  303.         else
  304.         {
  305.             if (*volatileVolumeList)
  306.                 *volatileVolumeList = (TList*)FreeIfObject(*volatileVolumeList);
  307.             aVolume = (TVolume*)FreeIfObject(aVolume);
  308.             fi.ReSignal();
  309.         }
  310.     }
  311.     else                                        // user cancelled or something 
  312.         aVolume = (TVolume *)(FreeIfObject(aVolume));    // free the unwanted file object 
  313.  
  314.     return volumeChosen;
  315. }
  316.  
  317. //----------------------------------------------------------------------------------------
  318. //    MVolumeBasedApp::ChooseVolume alternate old version
  319. //----------------------------------------------------------------------------------------    
  320. #pragma segment AOpen
  321. Boolean MVolumeBasedApp::ChooseVolume(CommandNumber itsCommandNumber, TVolume** aVolume)
  322. {
  323.  
  324.     typedef SFTypeList* SFTypeListPtr;
  325.     typedef SFTypeListPtr* SFTypeListHandle;
  326.  
  327.     
  328.     MAVolatileInit(TVolume*, aNewVolume, NULL);
  329.     Boolean volumeChosen;
  330.  
  331. #if !qPowerPC && !qModelCFM
  332.     if (HasCustomFile())
  333.     {
  334. #endif
  335.         ProcPtr fileFilter;
  336.         TypeListHandle typeList;
  337.         short dlgID;
  338.         CPoint where;
  339.         ProcPtr dlgHook;
  340.         ProcPtr modalFilter;
  341.         Ptr activeList;
  342.         ProcPtr activateProc;
  343.         StandardFileReply customReply;
  344.         void* yourDataPtr = NULL;
  345.         
  346.         gApplication -> GetStandardFileParameters(itsCommandNumber, fileFilter, typeList, dlgID, where,
  347.                                         dlgHook, modalFilter, activeList, activateProc,
  348.                                         &customReply, yourDataPtr);
  349.     
  350.         SFTypeListPtr pTypeList;
  351.         short numTypes = (short)(GetHandleSize((Handle)typeList) / sizeof(ResType));
  352.         if (numTypes == 0)
  353.         {
  354.             numTypes = -1;                            // Tell Std File to display all types.
  355.             pTypeList = (SFTypeListPtr) & pTypeList;// arbitrary, as long as it points to 4 bytes of valid memory
  356.         }
  357.         else
  358.         {
  359.             LockHandleHigh((Handle)typeList);        // in case Std File does allocations 
  360.             pTypeList = *((SFTypeListHandle)typeList);
  361.         }
  362.     
  363.         // Causes TApplication::GetEvent to call CheckRsrcUsage. 
  364.         gRsrcCheck = 0;
  365.     
  366.         FailInfo fi;
  367.         Try(fi)
  368.         {
  369.     
  370.             aNewVolume = this -> DoMakeVolume();
  371.             volumeChosen = FALSE;
  372.     
  373.             FailOSErr(gApplication->InteractWithUser(gNotificationPtr, TAppleEvent::fgIdleProc)); 
  374.     
  375.             if (yourDataPtr == NULL)
  376.                 yourDataPtr = &itsCommandNumber;
  377.             
  378.             gClipboardMgr->AboutToLoseControl(TRUE);            // so scrap gets converted
  379.             
  380.             FileFilterYDUPP cgfFileFilter = NewFileFilterYDProc(fileFilter);
  381.             DlgHookYDUPP cgfDlgHook = NewDlgHookYDProc(dlgHook);
  382.             ModalFilterYDUPP cgfModalFilter = NewModalFilterYDProc(modalFilter);
  383.             ActivateYDUPP cgfActivateProc = NewActivateYDProc(activateProc);
  384.  
  385.             CustomGetFile(cgfFileFilter, numTypes, (*pTypeList), &customReply, dlgID, where, cgfDlgHook, cgfModalFilter, (short*)activeList, cgfActivateProc, yourDataPtr);
  386.             
  387.             cgfFileFilter = (FileFilterYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfFileFilter);
  388.             cgfDlgHook = (DlgHookYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfDlgHook);
  389.             cgfModalFilter = (ModalFilterYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfModalFilter);
  390.             cgfActivateProc = (ActivateYDUPP)DisposeIfRoutineDescriptor((UniversalProcPtr)cgfActivateProc);
  391.             
  392.             gClipboardMgr->RegainControl(TRUE);            // so scrap gets converted
  393.  
  394.             volumeChosen = customReply.sfGood;
  395.             if (volumeChosen)
  396.                 {
  397.                 aNewVolume -> SpecifyWithStandardFileReply(customReply);
  398.     
  399.                 if (!(aNewVolume -> IsHFSVolume()))
  400.                     {
  401.                     CStr31 volumeName;
  402.                     aNewVolume -> GetName(volumeName);
  403.                     gErrorParm3 = volumeName;
  404.                     Failure(errNotHFSVolume, msgNotHFSVolume);
  405.                     }
  406.                 }
  407.                 
  408.             fi.Success();
  409.         }
  410.         else // Recover
  411.         {
  412.             typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  413.             aNewVolume = (TVolume *)FreeIfObject(aNewVolume);
  414.             fi.ReSignal();
  415.         }
  416.     
  417.         typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  418.  
  419.  
  420.  
  421. #if !qPowerPC && !qModelCFM
  422.         // the following block of code is the "else" block for the above Gestalt check - 
  423.         // as with that check, it is only relevant if we are not built for PowerPC
  424.     }
  425.     else
  426.     {
  427.         ProcPtr fileFilter;
  428.         TypeListHandle typeList;
  429.         short dlgID;
  430.         CPoint where;
  431.         ProcPtr dlgHook;
  432.         ProcPtr modalFilter;
  433.         Ptr activeList;
  434.         ProcPtr activateProc;
  435.         SFReply reply;
  436.         void* yourDataPtr = NULL;
  437.         
  438.         // We can't pass reply because it's a lowly SFReply, not a StandardFileReply
  439.         gApplication -> GetStandardFileParameters(itsCommandNumber, fileFilter, typeList, dlgID, where,
  440.                                         dlgHook, modalFilter, activeList, activateProc,
  441.                                         NULL, yourDataPtr);
  442.     
  443.         SFTypeListPtr pTypeList;
  444.         short numTypes = (short)(GetHandleSize((Handle)typeList) / sizeof(ResType));
  445.         if (numTypes == 0)
  446.         {
  447.             numTypes = -1;                            // Tell Std File to display all types.
  448.             pTypeList = (SFTypeListPtr) & pTypeList;// arbitrary, as long as it points to 4 bytes of valid memory
  449.         }
  450.         else
  451.         {
  452.             LockHandleHigh((Handle)typeList);        // in case Std File does allocations 
  453.             pTypeList = *((SFTypeListHandle)typeList);
  454.         }
  455.     
  456.         // Causes TApplication::GetEvent to call CheckRsrcUsage. 
  457.         gRsrcCheck = 0;
  458.     
  459.         FailInfo fi;
  460.         Try(fi)
  461.         {
  462.     
  463.             aNewVolume = this -> DoMakeVolume();
  464.             volumeChosen = FALSE;
  465.     
  466.             FailOSErr(gApplication->InteractWithUser(gNotificationPtr, TAppleEvent::fgIdleProc)); 
  467.     
  468.             if (yourDataPtr == NULL)
  469.                 yourDataPtr = &itsCommandNumber;
  470.             
  471.             // We will pass the address of the CallBack instead of the modalFilter to
  472.             // SFPGetFile It will add yourDataPtr parameter before passing on to the
  473.             // ModalFilterProc supplied by SFPutParms this lets us assume a single calling
  474.             // convention for that function.
  475.  
  476.             // Don't create a CallBack when the SF callback is NULL.
  477.             // Also, pass itsCommandNumber as a default yourDataPtr.
  478.             
  479.             CallBack myFileFilterCallBack;
  480.             SetCallBack(fileFilter, (long)yourDataPtr, &myFileFilterCallBack);
  481.             FileFilterProcPtr aFileFilterProcPtr = fileFilter ? (FileFilterProcPtr)&myFileFilterCallBack : NULL;
  482.  
  483.             CallBack myModalHookCallBack;
  484.             SetCallBack(dlgHook, (long)yourDataPtr, &myModalHookCallBack);
  485.             DlgHookProcPtr aDlgHookProcPtr = dlgHook ? (DlgHookProcPtr)&myModalHookCallBack : NULL;
  486.     
  487.             CallBack myModalFilterCallBack;
  488.             SetCallBack(modalFilter, (long)yourDataPtr, &myModalFilterCallBack);
  489.             ModalFilterProcPtr aModalFilterProcPtr = modalFilter ? (ModalFilterProcPtr)&myModalFilterCallBack : NULL;
  490.  
  491.             gClipboardMgr->AboutToLoseControl(TRUE);    // so scrap gets converted
  492.  
  493.             SFPGetFile(where, gEmptyString, aFileFilterProcPtr, numTypes, (*pTypeList), aDlgHookProcPtr, &reply, dlgID, aModalFilterProcPtr);
  494.             
  495.             gClipboardMgr->RegainControl(TRUE);            // so scrap gets converted
  496.  
  497.             volumeChosen = reply.good;
  498.  
  499.             if (volumeChosen)
  500.                 {
  501.                 FailOSErr(aNewVolume -> SpecifyWithSFReply(reply));
  502.     
  503.                 if (!(aNewVolume -> IsHFSVolume()))
  504.                     {
  505.                     CStr31 volumeName;
  506.                     aNewVolume -> GetName(volumeName);
  507.                     gErrorParm3 = volumeName;
  508.                     Failure(errNotHFSVolume, msgNotHFSVolume);
  509.                     }
  510.                 }
  511.                 
  512.             fi.Success();
  513.         }
  514.         else // Recover
  515.         {
  516.             typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  517.             aNewVolume = (TVolume *)FreeIfObject(aNewVolume);
  518.             fi.ReSignal();
  519.         }
  520.     
  521.         typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  522.  
  523.     }
  524. #endif
  525.  
  526.     if (volumeChosen)
  527.     {
  528.         MAVolatileInit(TVolume**, volatileVolume, aVolume);
  529.         
  530.         FailInfo fi;
  531.         Try(fi)
  532.         {
  533.             // Return the volume chosen 
  534.             *volatileVolume = aNewVolume;
  535.             fi.Success();
  536.         }
  537.         else
  538.         {
  539.             if (*volatileVolume)
  540.                 *volatileVolume = (TVolume*)FreeIfObject(*volatileVolume);
  541.             aNewVolume = (TVolume*)FreeIfObject(aNewVolume);
  542.             fi.ReSignal();
  543.         }
  544.     }
  545.     else                                        // user cancelled or something 
  546.         aNewVolume = (TVolume*)(FreeIfObject(aNewVolume));    // free the unwanted volume object 
  547.  
  548.     return volumeChosen;
  549. }
  550. //----------------------------------------------------------------------------------------
  551. // MVolumeBasedApp::CanOpenVolume:    analog of CanOpenDocument
  552. //----------------------------------------------------------------------------------------
  553. #pragma segment MAFinder
  554. // This is called only when opening/printing from the finder and from standard file;
  555. // it simulates the filtering done by Std File.
  556.  
  557. Boolean MVolumeBasedApp::CanOpenVolume(CommandNumber itsCommandNumber, TVolume* aVolume)
  558. {
  559.     Boolean returnValue = FALSE;
  560.     
  561.     ProcPtr fileFilter;
  562.     TypeListHandle typeList = NULL;
  563.     short dlgID;
  564.     CPoint where;
  565.     ProcPtr dlgHook;
  566.     ProcPtr modalFilter;
  567.     Ptr activeList;
  568.     ProcPtr activateProc;
  569.     void* yourDataPtr = NULL;
  570.  
  571.     gApplication -> GetStandardFileParameters(itsCommandNumber, fileFilter, typeList, dlgID, where,
  572.                                     dlgHook, modalFilter, activeList, activateProc,
  573.                                     NULL, yourDataPtr);
  574.  
  575.     CStr31 volumeName;
  576.     aVolume -> GetName(volumeName);
  577.  
  578.     CInfoPBRec paramBlock;
  579.  
  580.     short numTypes = (short)(GetHandleSize((Handle)typeList) / sizeof(ResType));
  581.     if (numTypes == 0)
  582.     {
  583.         if (!fileFilter)
  584.             returnValue = TRUE;                    // no file filter then want all types
  585.         else if (aVolume -> GetCatInfo(paramBlock) == noErr)
  586.         {
  587.             paramBlock.hFileInfo.ioNamePtr = (StringPtr)volumeName;
  588.             // Call through the supplied filterProc
  589.             returnValue = !((FileFilterYDProcPtr)fileFilter)(¶mBlock, NULL);
  590.         }
  591.         else
  592.             returnValue = FALSE;
  593.     }
  594.     else
  595.     {
  596.         for (short i = 0; i < numTypes; ++i)
  597.         {
  598.             if (((long)(aVolume->fFileType)) == ((long)(*typeList)[i]))
  599.             {
  600.                 if (!fileFilter)
  601.                     returnValue = TRUE;
  602.                 else if (aVolume -> GetCatInfo(paramBlock) == noErr)
  603.                 {
  604.                     paramBlock.hFileInfo.ioNamePtr = (StringPtr)volumeName;
  605.                     // Call through the supplied filterProc
  606.                     returnValue = !((FileFilterYDProcPtr)fileFilter)(¶mBlock, NULL);
  607.                 }
  608.                 else
  609.                     returnValue = FALSE;
  610.                 break;
  611.             }
  612.         }
  613.     }
  614.  
  615.     typeList = (TypeListHandle)DisposeIfHandle((Handle)typeList);
  616.     return returnValue;
  617. }
  618. //----------------------------------------------------------------------------------------
  619. // MVolumeBasedApp::OpenVolume:    analog of OpenOld new version
  620. //----------------------------------------------------------------------------------------
  621. #pragma segment AOpen
  622. TDocument* MVolumeBasedApp::OpenVolume(CommandNumber itsOpenCommand, TList* aVolumeList)
  623. {
  624.     MAVolatileInit(TDocument*, aDocument, NULL);
  625.     MAVolatileInit(TVolume*, aVolume, NULL);
  626.     MAVolatileInit(TVolume*, aNewVolume, NULL);    
  627.     MAVolatileInit(OSErr, savedError, 0);
  628.     MAVolatileInit(long, savedMessage, 0);
  629.  
  630.     Size oldCodeReserve;    // can't be volatile because it is passed by reference
  631.     Size oldMemReserve;        // can't be volatile because it is passed by reference
  632.  
  633.     {
  634.         // Put iterator in a separate block so that it will go out of scope before the end of the method.
  635.         // We don't want the iterator's failure handler to be invoked, because its stack ptr is munged.
  636.         // If an error occurs, we'll just save it and ReSignal it after the iterator is gone.
  637.         
  638.         CObjectIterator iter(aVolumeList);
  639.         for (aVolume = (TVolume *)iter.FirstObject(); iter.More() && !savedError; aVolume = (TVolume *)iter.NextObject())
  640.         {
  641.             CommandNumber kindOfDocCmd = itsOpenCommand;
  642.             // reset aDocument and aNewVolume so that they no longer refer to items from the
  643.             // last go round (important in case we fail downstream)…
  644.             aDocument = NULL;
  645.             aNewVolume = NULL;
  646.             
  647.             CStr31 volumeName;
  648.             aVolume -> GetName(volumeName);        // If failure occurs the file may already be
  649.                                                 // freed so we will save the name just in
  650.                                                 // case.
  651.             
  652.             aVolumeList -> Delete(aVolume);        // ReadStationery if successful will dispose
  653.                                                 // of the file for us so if failure occurs
  654.                                                 // this had better not be in the file list.
  655.             
  656.             FailInfo fi;
  657.             Try(fi)
  658.             {
  659.                 // Set reserve down a little to ensure that we can open existing documents 
  660.                 GetReserveSize(oldCodeReserve, oldMemReserve);
  661.                 SetReserveSize(oldCodeReserve, oldMemReserve / 2);
  662.                 
  663.                 TDocument * otherDoc = NULL;        //For testing purposes, I find it useful to set otherDoc = NULL
  664.                                                                                 //which allows the same volume to be opened as many times
  665.                                                                                 //as needed to stress memory and induce failure. For a
  666.                                                                                 //shipping application, you don't want the user to be able
  667.                                                                                 //to open the same volume again and again so comment out the 
  668.                                                                                 //following if statement which, of course, allows the same volume 
  669.                                                                                 //to be opened more than once if fAllowUnlimitedDocs is TRUE. 
  670.  
  671.                 if (!gTwistDownApp -> fAllowUnlimitedDocs)
  672.                     otherDoc = gTwistDownApp -> FindDocument(aVolume);
  673.                                                                                 
  674.                 if (otherDoc)
  675.                 {
  676.                     otherDoc -> OpenAgain(kindOfDocCmd, aDocument);
  677.                     aVolume = (TVolume*)FreeIfObject(aVolume);
  678.                     SetReserveSize(oldCodeReserve, oldMemReserve);
  679.                 }
  680.                 else if (this -> CanOpenVolume(kindOfDocCmd, aVolume))
  681.                 {
  682.                     if (!(aVolume -> IsHFSVolume()))
  683.                         {
  684.                         gErrorParm3 = volumeName;
  685.                         Failure(errNotHFSVolume, msgNotHFSVolume);
  686.                         }
  687.                     
  688.                     TVolume* volumeOwnedByDoc = aVolume;
  689.                     aVolume = NULL;
  690.                     
  691.                     FailNIL(aDocument = gTwistDownApp -> DoMakeDocument(kindOfDocCmd, volumeOwnedByDoc));
  692.                     
  693.                     aDocument -> ReadDocument(kForDisplay);
  694.  
  695.                     aDocument -> DoMakeViews(kForDisplay);
  696.                     
  697.  
  698.                         
  699.                     FailSpaceIsLow();                // Fail if the document leaves us with no
  700.                                                                     // memory
  701.                         
  702.                     // Set the reserve back to where it was 
  703.                     SetReserveSize(oldCodeReserve, oldMemReserve);
  704.         
  705.                     // Don't attempt to show the windows until we're sure we won't fail 
  706.                     aDocument -> DoPostMakeViews(kForDisplay);
  707.                 }
  708.                 else
  709.                     Failure(errNotMyType, 0);
  710.                 fi.Success();
  711.             }
  712.             else // Recover
  713.             {
  714.                 if (fi.message == 0 || fi.message == msgTooManyRows)
  715.                     gErrorParm3 = volumeName;
  716.         
  717.                 // We may have ended up without a document because of a failure during document
  718.                 // init. b/c this can be the case we don't know what happened to aVolume, whether 
  719.                 // it was freed by the document in the failure process or orphaned. Because of
  720.                 // this we will not free aVolume here.
  721.                 if (aDocument)
  722.                     //aDocument = (TDocument *)(FreeIfObject(aDocument));    // The document will free the file
  723.                     aDocument -> CloseAndFree();     //Use CloseAndFree because it removes the TWindow
  724.                                                                                 //associated with fTwistDownView from the windows
  725.                                                                                 //list if necessary. This window must be removed
  726.                                                                                 //from the list before it is freed. If it isn't
  727.                                                                                 //the program will crash the machine with an 
  728.                                                                                 //access fault. 
  729.                                                                                     
  730.                 aNewVolume = (TVolume*)FreeIfObject(aNewVolume);    // If we successfully read the
  731.                                                                                                                     // stationery then aNewVolume will
  732.                                                                                                                     // be NULL
  733.                 
  734.                 // Set the reserve back to where it was 
  735.                 SetReserveSize(oldCodeReserve, oldMemReserve);
  736.                 
  737.                 //    Don't want to fail here, because the CObjectIterator (with its embedded FailInfo) is 
  738.                 //    still in scope. Instead, save the error info until after the iterator has self-destructed.
  739.                 //    FailNewMessage(fi.error, fi.message, messageOpenFailed);
  740.                 savedError = fi.error;
  741.                 savedMessage = fi.message;
  742.                 if (!savedMessage)
  743.                     savedMessage = messageOpenFailed;
  744.             }
  745.         }
  746.     } // iterator will self-destruct now
  747.  
  748.       if (savedError != noErr)                        // Do we need to ReSignal a failure?
  749.     {
  750.         // signal the failure
  751.         Failure(savedError, savedMessage);
  752.     }
  753.  
  754.     return aDocument;
  755. }
  756. //----------------------------------------------------------------------------------------
  757. // MVolumeBasedApp::OpenVolume: alternate old version
  758. //----------------------------------------------------------------------------------------
  759. #pragma segment AOpen
  760. TDocument* MVolumeBasedApp::OpenVolume(CommandNumber itsOpenCommand, TVolume* volumeOwnedByDoc)
  761. {
  762.     
  763.     MAVolatileInit(TDocument*, aDocument, NULL);
  764.     
  765.     FailInfo fi;
  766.     Try(fi)
  767.     {
  768.  
  769.         CommandNumber kindOfDocCmd = itsOpenCommand;
  770.         
  771.         FailNIL(aDocument = gTwistDownApp -> DoMakeDocument(kindOfDocCmd, volumeOwnedByDoc));            
  772.  
  773.         aDocument -> ReadDocument(kForDisplay);
  774.         FailSpaceIsLow();                        // Fail if document leaves us with no room In UMemory    
  775.         
  776.         aDocument -> DoMakeViews(kForDisplay);
  777.         FailSpaceIsLow();                        // Fail if document leaves us with no room In UMemory
  778.         
  779.         // Don't attempt to show the windows until we're sure we won't fail 
  780.         aDocument -> DoPostMakeViews(kForDisplay);                
  781.                                                                                         
  782.         fi.Success();
  783.     }
  784.     else                                        // Recover
  785.     {        
  786.         if (aDocument)
  787.             {
  788.             //aDocument = (TDocument *)(FreeIfObject(aDocument));
  789.             aDocument -> CloseAndFree();     //Use CloseAndFree because it removes the TWindow
  790.                                                                         //associated with fTwistDownView from the windows
  791.                                                                         //list if necessary. This window must be removed
  792.                                                                         //from the list before it is freed. If it isn't
  793.                                                                         //the program will crash the machine with an 
  794.                                                                         //access fault.
  795.             aDocument = NULL;
  796.             }
  797.             
  798.         FailNewMessage(fi.error, fi.message, messageNewFailed);
  799.         fi.ReSignal();
  800.     }
  801.     
  802.  
  803.     return aDocument;
  804.  
  805. }
  806.  
  807. #pragma segment Inline